             package com.java.diagnostics.visualizer.gc.realtimeV2.parser;
             
             import com.java.diagnostics.visualizer.data.TupleDataBuilder;
             import com.java.diagnostics.visualizer.data.axes.AxisPair;
             import com.java.diagnostics.visualizer.factory.DataFactory;
             import com.java.diagnostics.visualizer.gc.realtime.util.Messages;
             import com.java.diagnostics.visualizer.metadata.TupleMetaData;
             import com.java.diagnostics.visualizer.metadata.TupleMetaData.TableField;
             import com.java.diagnostics.visualizer.metadata.TupleMetaData.TableType;
             import org.xml.sax.Attributes;
             
             public class SynchGCParser
               extends GCEventParser
             {
               public static final String SYNCHRONOUSGCPRIORITY = "synchronousgcpriority";
               private static final String DURATION = "duration";
               private static final String REASON = "reason";
               private static final String SYSTEM_GARBAGE_COLLECT = "system garbage collect";
               private static final String OUT_OF_MEMORY = "out of memory";
               private static final String VM_SHUTDOWN = "vm shutdown";
               private static final String UNKNOWN_REASON = "unkown reason";
               private static final String FREEBYTESBEFORE = "freebytesbefore";
               private static final String FREEBYTESAFTER = "freebytesafter";
               private static final String VALUE = "value";
               private static final String TIMEMS = "timems";
               private final boolean filterSystemGCs;
               private int eventConstant;
               private String eventLabel;
               boolean hasImmortal;
               double durationMillis;
               boolean ignore;
               int synchGCCount;
               TupleDataBuilder durations;
               private StoredPoints startPoints = new StoredPoints(9);
               private StoredPoints endPoints = new StoredPoints(4);
               
               SynchGCParser(CommonData commonData, boolean filterSystemGCs, DataFactory factory, AxisPair timePair)
               {
                 super(commonData);
                 this.filterSystemGCs = filterSystemGCs;
                 this.durations = factory
                 
                   .createTupleData("RealtimeLabels.synch.gc.durations", Messages.getString("RealtimeLabels.synch.gc.durations"), timePair);
                 TupleMetaData durationsMetaData = new TupleMetaData(
                   TupleMetaData.TableType.ARITHMETIC, new TupleMetaData.TableField[] { TupleMetaData.TableField.MEAN, 
                   TupleMetaData.TableField.MIN, TupleMetaData.TableField.MAX });
                 this.durations.setTupleMetaData(durationsMetaData);
               }
               
               boolean startElement(String uri, String localName, String name, Attributes atts, String comment)
               {
                 boolean ret;
                 
                 //boolean ret;
                 
                 if (this.ignore) {
                   ret = super.startElement(uri, localName, name, atts, comment);
                 }
                 else {
                   ret = true;
                   if (name.equals("details")) {
                     String reason = atts.getValue("reason");
                     if (reason != null) {
                       if (reason.equals("system garbage collect")) {
                         this.eventConstant = 2;
                         this.eventLabel = "sys";
                         this.ignore = this.filterSystemGCs;
                       } else if (reason.equals("out of memory")) {
                         this.eventConstant = 13;
                         this.eventLabel = "OOM GC";
                       }
                       else if (reason.equals("vm shutdown")) {
                         this.eventConstant = 14;
                         this.eventLabel = "shutdown GC";
                       }
                       else
                       {
                         this.eventConstant = 1;
                         this.eventLabel = "synchgc";
                       }
                     }
                   } else if (name.equals("duration")) {
                     this.durationMillis = CommonData.convertPositiveDouble(
                       atts.getValue("timems"));
                     if (this.durationMillis >= 0.0D) {
                       this.endPoints.storePoint(this.durations, this.durationMillis, comment);
                     }
                   } else if (name.equals("warning")) {
                     this.commonData.handleWarning(atts, this.timeMicros / 1000L, comment);
                   } else if (name.equals("classunloading")) {
                     long classesCount = CommonData.getClassesUnloaded(atts);
                     if (classesCount >= 0L) {
                       this.endPoints.storePoint(this.commonData.classesUnloaded, 
                         classesCount, comment);
                     }
                     long loaderCount = CommonData.getClassLoadersUnloaded(atts);
                     if (loaderCount >= 0L) {
                       this.endPoints.storePoint(this.commonData.classloadersUnloaded, 
                         loaderCount, comment);
                     }
                   } else if (name.equals("refs_cleared")) {
                     long refsCleared = CommonData.getSoftRefsCleared(atts);
                     if (refsCleared >= 0L) {
                       this.endPoints.storePoint(this.commonData.softRefsCleared, 
                         refsCleared, comment);
                     }
                     refsCleared = CommonData.getWeakRefsCleared(atts);
                     if (refsCleared >= 0L) {
                       this.endPoints.storePoint(this.commonData.weakRefsCleared, 
                         refsCleared, comment);
                     }
                     refsCleared = CommonData.getPhantomRefsCleared(atts);
                     if (refsCleared >= 0L) {
                       this.endPoints.storePoint(this.commonData.phantomRefsCleared, 
                         refsCleared, comment);
                     }
                   } else if (name.equals("finalization")) {
                     long finalized = CommonData.getFinalizedCount(atts);
                     if (finalized >= 0L)
                       this.endPoints.storePoint(
                         this.commonData.objectsQueuedForFinalization, finalized, 
                         comment);
                   } else { boolean isHeap;
                     if (((isHeap = name.equals("heap"))) || 
                       (name.equals("immortal"))) {
                       this.hasImmortal |= !isHeap;
                       long before = CommonData.convertPositiveInteger(atts
                         .getValue("freebytesbefore"));
                       if (before >= 0L) {
                         TupleDataBuilder data1 = isHeap ? this.commonData.minFreeHeap : 
                           this.commonData.minFreeImmortal;
                         TupleDataBuilder data2 = isHeap ? this.commonData.maxFreeHeap : 
                           this.commonData.maxFreeImmortal;
                         TupleDataBuilder data3 = isHeap ? this.commonData.meanFreeHeap : 
                           this.commonData.meanFreeImmortal;
                         this.startPoints.storePoint(data1, before, comment);
                         this.startPoints.storePoint(data2, before, comment);
                         this.startPoints.storePoint(data3, before, comment);
                         if (isHeap) {
                           this.startPoints.storePoint(this.commonData.freeHeap, before, 
                             comment);
                         }
                       }
                       long after = CommonData.convertPositiveInteger(atts
                         .getValue("freebytesafter"));
                       if (after >= 0L) {
                         TupleDataBuilder data1 = isHeap ? this.commonData.minFreeHeap : 
                           this.commonData.minFreeImmortal;
                         TupleDataBuilder data2 = isHeap ? this.commonData.maxFreeHeap : 
                           this.commonData.maxFreeImmortal;
                         TupleDataBuilder data3 = isHeap ? this.commonData.meanFreeHeap : 
                           this.commonData.meanFreeImmortal;
                         this.endPoints.storePoint(data1, after, comment);
                         this.endPoints.storePoint(data2, after, comment);
                         this.endPoints.storePoint(data3, after, comment);
                         if (isHeap) {
                           this.endPoints.storePoint(this.commonData.freeHeap, after, 
                             comment);
                         }
                       }
                     } else if (name.equals("synchronousgcpriority")) {
                       long val = CommonData.convertPositiveInteger(atts
                         .getValue("value"));
                       if (val >= 0L)
                       {
                         this.startPoints.storePoint(this.commonData.maxpriority, val, comment);
                         this.startPoints
                           .storePoint(this.commonData.minpriority, val, comment);
                         this.endPoints.storePoint(this.commonData.maxpriority, val, comment);
                         this.endPoints.storePoint(this.commonData.minpriority, val, comment);
                       }
                     } else {
                       ret = super.startElement(uri, localName, name, atts, comment);
                     }
                   } }
                 if (!ret) {
                   complete();
                 }
                 return ret;
               }
               
               private void complete() {
                 if (!this.ignore) {
                   this.synchGCCount += 1;
                   double timeMillis = this.timeMicros / 1000.0D;
                   
                   this.commonData.currentGCNumber += 1L;
                   double synchStartMillis = timeMillis;
                   this.commonData.setXAxis(synchStartMillis);
                   
                   double lastGCCycleMillis = Math.max(this.commonData
                     .getInitialTimeMicros() / 
                     1000.0D, this.commonData.lastGCCycleMillis);
                   this.startPoints.storePoint(this.commonData.cycleIntervals, synchStartMillis - 
                     lastGCCycleMillis, this.initialComment);
                   this.startPoints.complete();
                   
                   double endTimeMillis = timeMillis + this.durationMillis;
                   this.commonData.lastGCCycleMillis = endTimeMillis;
                   
                   if (this.durationMillis > 0.0D) {
                     this.commonData.currentGCNumber += 1L;
                     this.commonData.setXAxis(endTimeMillis);
                     this.endPoints.complete();
                   }
                   
                   this.commonData.completeGCEvent(this.eventLabel, this.eventConstant, this.id, 
                     this.initialComment);
                 }
               }
               
               void init(long micros, String initialComment, long intervalMicros)
               {
                 super.init(micros, initialComment, intervalMicros);
                 this.startPoints.init();
                 this.endPoints.init();
                 this.durationMillis = 0.0D;
                 this.ignore = false;
                 this.eventConstant = 1;
                 this.eventLabel = "synchgc";
               }
               
               boolean endElement(String uri, String localName, String name, String comment)
               {
                 boolean ret = super.endElement(uri, localName, name, comment);
                 if (!ret) {
                   complete();
                 }
                 return ret;
               }
             }


